import 'dart:io';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:dart_bean/cass_info.dart';
import 'package:dart_bean/feature/custom_json_converter.dart';
import 'package:dart_bean/feature/enum_field.dart';
import 'package:dart_bean/field_info.dart';
import 'package:dart_bean/generator.dart';
import 'package:dart_bean/util/error_tip.dart';

class ClassVisitor extends RecursiveAstVisitor {
  final File file;

  ClassVisitor(this.file);

  final List<ClassDeclaration> classDeclarations = [];
  final List<ImportDirective> imports = [];
  final List<PartDirective> parts = [];

  @override
  visitClassDeclaration(ClassDeclaration node) {
    CustomJsonConverterFeature.visitClassDeclaration(file, node);
    if (isJsonSerializable(node)) classDeclarations.add(node);
    return super.visitClassDeclaration(node);
  }

  bool isJsonSerializable(ClassDeclaration p) {
    return p.metadata.any((e) => e.name.name == 'JsonSerializable');
  }

  @override
  visitEnumDeclaration(EnumDeclaration node) {
    EnumFieldFeature.visitEnumDeclaration(file, node);
    return super.visitEnumDeclaration(node);
  }

  @override
  visitImportDirective(ImportDirective node) {
    imports.add(node);
    return super.visitImportDirective(node);
  }

  @override
  visitPartDirective(PartDirective node) {
    parts.add(node);
    return super.visitPartDirective(node);
  }
}

class FieldVisitor extends RecursiveAstVisitor {
  final CassInfo _cassInfo;
  final List<FieldInfo> fields = [];

  FieldVisitor(CassInfo cassInfo) : _cassInfo = cassInfo;

  @override
  visitFieldDeclaration(FieldDeclaration node) {
    for (var e in node.fields.variables) {
      final type = node.fields.type;
      final f = FieldInfo(_cassInfo, node, type?.toString() ?? '', e.name.toString());
      if (type == null && !f.isIgnoreDeserialize) {
        final msg = '$unsupportedVarTypeNameError\n${_cassInfo.file.path}\n ${_cassInfo.name} -> $node';
        onError(msg);
      }
      fields.add(f);
    }

    return super.visitFieldDeclaration(node);
  }
}

class DartClassDeclaration {
  final File file;
  final ClassDeclaration self;
  List<FieldInfo> fields = [];

  DartClassDeclaration(this.file, this.self);
}
